package com.sc.nft.util;

import com.google.common.collect.Lists;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;

/**
 * BigDecimal工具类
 *
 * @author liGen
 * @version 1.0
 * @date 2023/11/15 1:35 下午
 */
public class BigDecimalUtils {


    /**
     * TURE 大于等于 0
     *
     * @param o
     * @return
     */
    public static Boolean greaterEqZero(Object o) {
        //@return -1, 0, or 1 as this {@code BigDecimal} is numerically
        //     *          less than, equal to, or greater than {@code val}.
        BigDecimal bigDecimal = p(o);
        return bigDecimal.compareTo(BigDecimal.ZERO) >= 0;
    }

    /**
     * TRUE 大于 0
     *
     * @param o
     * @return
     */
    public static Boolean greaterZero(Object o) {
        BigDecimal bigDecimal = p(o);
        return bigDecimal.compareTo(BigDecimal.ZERO) > 0;
    }

    /**
     * TRUE  first 大于等于second
     *
     * @param first
     * @param second
     * @return
     */
    public static Boolean compareTo(Object first, Object second) {
        BigDecimal _f = p(first);
        BigDecimal _s = p(second);
        return _f.compareTo(_s) >= 0;
    }

    /**
     * TRUE  first 等于second
     *
     * @param first
     * @param second
     * @return
     */
    public static Boolean eq(Object first, Object second) {
        BigDecimal _f = p(first);
        BigDecimal _s = p(second);
        return _f.compareTo(_s) == 0;
    }

    /**
     * TRUE  first 大于second
     *
     * @param first
     * @param second
     * @return
     */
    public static Boolean compare(Object first, Object second) {
        BigDecimal _f = p(first);
        BigDecimal _s = p(second);
        return _f.compareTo(_s) > 0;
    }

    /**
     * 加
     *
     * @param o
     * @return
     */
    public static BigDecimal add(Object... o) {
        List<Object> _list = Arrays.asList(o);
        BigDecimal _total = BigDecimal.ZERO;
        for (Object _o : _list) {
            if (null == _o) {
                continue;
            }
            _total = _total.add(p(_o));
        }
        return _total;
    }


    /**
     * 减
     *
     * @param o
     * @return
     */
    public static BigDecimal subtract(Object cardinal, Object... o) {

        List<Object> _list = Arrays.asList(o);
        BigDecimal _total = p(cardinal);
        for (Object _o : _list) {
            _total = _total.subtract(p(_o));
        }
        return _total;
    }


    /**
     * 乘法
     *
     * @param o
     * @return
     */
    public static BigDecimal multiplys(Object... o) {

        List<Object> _list = Arrays.asList(o);
        BigDecimal _total = BigDecimal.ONE;
        for (Object _o : _list) {
            _total = _total.multiply(p(_o)).setScale(6, RoundingMode.UP);
        }
        return _total;
    }

    /**
     * 乘法
     *
     * @param o
     * @return
     */
    public static BigDecimal multiplys(Integer scale, RoundingMode roundingMode,Object... o) {

        List<Object> _list = Arrays.asList(o);
        BigDecimal _total = BigDecimal.ONE;
        for (Object _o : _list) {
            _total = _total.multiply(p(_o)).setScale(scale, roundingMode);
        }
        return _total;
    }


    /**
     * 除
     *
     * @param cardinal
     * @param divisiend
     * @return
     */
    public static BigDecimal divide(Object cardinal, Object divisiend) {

        BigDecimal _cardinal = p(cardinal);
        BigDecimal _divisiend = p(divisiend);
        return _cardinal.divide(_divisiend, 10, RoundingMode.HALF_UP);
    }

    /**
     * 除
     *
     * @param cardinal
     * @param divisiend
     * @return
     */
    public static BigDecimal divide(Object cardinal, Object divisiend, Integer scale, RoundingMode roundingMode) {

        BigDecimal _cardinal = p(cardinal);
        BigDecimal _divisiend = p(divisiend);
        return _cardinal.divide(_divisiend, scale, roundingMode);
    }


    /**
     * 计算百分比
     *
     * @param cardinal
     * @param divisiend
     * @return
     */
    public static String rate(Object cardinal, Object divisiend) {
        BigDecimal _cardinal = p(cardinal);
        BigDecimal _divisiend = p(divisiend);
        if (_divisiend.compareTo(BigDecimal.ZERO) == 0) {
            return "0%";
        }
        BigDecimal _divResult = _cardinal.divide(_divisiend, 4, RoundingMode.HALF_UP);
        BigDecimal _r = BigDecimalUtils.multiplys(_divResult, BigDecimalUtils.p(100));
        return _r.toString() + "%";
    }

    /**
     * 将对象转 BigDecimal
     *
     * @param o
     * @return
     */
    public static BigDecimal p(Object o) {
        Double d = parse(o);
        return BigDecimal.valueOf(d);
    }

    public static Double parse(Object o) {
        if (o == null) {
            return 0D;
        } else if (o instanceof Number) {
            return ((Number) o).doubleValue();
        } else {
            return o instanceof String ? Double.parseDouble(o.toString()) : Double.parseDouble(o.toString());
        }
    }

    public static BigDecimal getRandomBigDecimal(BigDecimal min, BigDecimal max) {
        Random random = new Random();
        // 生成[0,1)之间的随机BigDecimal
        BigDecimal randomBigDecimal = new BigDecimal(random.nextDouble(), new MathContext(2, RoundingMode.HALF_UP));
        // 计算区间宽度
        BigDecimal diff = max.subtract(min);
        // 生成[min,max]区间内的随机数
        BigDecimal result = min.add(randomBigDecimal.multiply(diff, new MathContext(2, RoundingMode.HALF_UP)));
        return result;
    }

    public static void main(String[] args) {
        List<Long> allList = Lists.newArrayList();
        ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(8);
        for (int i = 0; i < 5; i++) {
            Future<?> future =  threadPoolExecutor.submit((Callable) () -> {
                List<Long> list = Lists.newArrayList();
                try {
                    list.add(1L);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
                return list;
            });
            try {
                List<Long> list = (List<Long>) future.get();
                allList.addAll(list);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } catch (ExecutionException e) {
                throw new RuntimeException(e);
            }
        }
        System.out.println(allList);
        threadPoolExecutor.shutdown();
    }

}
